package instruct

import "go_jvm/thread"

/**
  nop
  const
  bipush sipush
  ILOAD
*/
// nop 指令
type Nop struct{ NoOperandsInstruction }

func (self *Nop) Execute(frame *thread.Frame) {
	// do noting
}

// const 指令
type ACONST_NULL struct{ NoOperandsInstruction } // 把null 引用推入操作数栈顶
type DCONST_0 struct{ NoOperandsInstruction }    // 把 double 0  推入操作数栈顶
type DCONST_1 struct{ NoOperandsInstruction }    // 把 double 1  推入操作数栈顶
type FCONST_0 struct{ NoOperandsInstruction }    // 把 float 0  推入操作数栈顶
type FCONST_1 struct{ NoOperandsInstruction }    //把 float 1  推入操作数栈顶
type FCONST_2 struct{ NoOperandsInstruction }    //把 float 2  推入操作数栈顶
type ICONST_0 struct{ NoOperandsInstruction }
type ICONST_1 struct{ NoOperandsInstruction }
type ICONST_M1 struct{ NoOperandsInstruction }
type ICONST_2 struct{ NoOperandsInstruction }
type ICONST_3 struct{ NoOperandsInstruction }
type ICONST_4 struct{ NoOperandsInstruction }
type ICONST_5 struct{ NoOperandsInstruction }
type LCONST_0 struct{ NoOperandsInstruction }
type LCONST_1 struct{ NoOperandsInstruction }

func (self *ACONST_NULL) Execute(frame *thread.Frame) {
	frame.OperandStack.PushRef(nil)
}

func (self *DCONST_0) Execute(frame *thread.Frame) {
	frame.OperandStack.PushDouble(0.0)
}

func (self *DCONST_1) Execute(frame *thread.Frame) {
	frame.OperandStack.PushDouble(1.0)
}

func (self *FCONST_0) Execute(frame *thread.Frame) {
	frame.OperandStack.PushFloat(0.0)
}

func (self *FCONST_1) Execute(frame *thread.Frame) {
	frame.OperandStack.PushFloat(1.0)
}

func (self *FCONST_2) Execute(frame *thread.Frame) {
	frame.OperandStack.PushFloat(2.0)
}

func (self *ICONST_0) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(0)
}

func (self *ICONST_1) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(1)
}

func (self *ICONST_M1) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(-1)
}

func (self *ICONST_2) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(2)
}

func (self *ICONST_3) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(3)
}

func (self *ICONST_4) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(4)
}

func (self *ICONST_5) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(5)
}

func (self *LCONST_0) Execute(frame *thread.Frame) {
	frame.OperandStack.PushLong(0)
}

func (self *LCONST_1) Execute(frame *thread.Frame) {
	frame.OperandStack.PushLong(1)
}

// BIPUSH 指令 从操作数栈中获取一个byte型整数 拓展成int 然后推入栈顶
type BIPUSH struct{ val int8 }

// SIPUSH 指令 从操作数栈中获取一个short型整数 拓展成int 然后推入栈顶
type SIPUSH struct{ val int16 }

func (self *BIPUSH) FetchOperands(reader *ByteCodeReader) {
	self.val = (*reader).ReadInt8()
}
func (self *BIPUSH) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(int32(self.val))
}

func (self *SIPUSH) FetchOperands(reader *ByteCodeReader) {
	self.val = (*reader).ReadInt16()
}
func (self *SIPUSH) Execute(frame *thread.Frame) {
	frame.OperandStack.PushInt(int32(self.val))
}

// 加载指令 LOAD
type ILOAD struct{ Index8Instruction }
type ILOAD_0 struct{ NoOperandsInstruction }
type ILOAD_1 struct{ NoOperandsInstruction }
type ILOAD_2 struct{ NoOperandsInstruction }
type ILOAD_3 struct{ NoOperandsInstruction }

func (self *ILOAD) Execute(frame *thread.Frame) {
	_ILoad(frame, int(self.Offset))
}

func (self *ILOAD_0) Execute(frame *thread.Frame) {
	_ILoad(frame, 0)
}

func (self *ILOAD_1) Execute(frame *thread.Frame) {
	_ILoad(frame, 1)
}
func (self *ILOAD_2) Execute(frame *thread.Frame) {
	_ILoad(frame, 2)
}
func (self *ILOAD_3) Execute(frame *thread.Frame) {
	_ILoad(frame, 3)
}

func _ILoad(frame *thread.Frame, index int) {
	val := frame.LocalVarList.GetInt(index)
	frame.OperandStack.PushInt(val)
}
